<?php

/**
 * This is the model class for table "sd.goods".
 *
 * The followings are the available columns in table 'sd.goods':
 * @property string $id
 * @property string $code
 * @property string $category_id
 * @property string $color_bind
 * @property string $title
 * @property string $alias
 * @property string $short_description
 * @property string $description
 * @property string $meta_keywords
 * @property string $meta_description
 * @property integer $active
 * @property integer $is_available
 * @property integer $is_new
 * @property integer $quantity
 * @property double $price
 * @property integer $user_add
 * @property integer $user_edit
 * @property string $date_add
 * @property string $date_edit
 * @property integer $sort
 * @property string $original_url
 * @property string $original_title
 * @property string $original_description
 * @property integer $is_top
 * @property string $related
 * @property string $parser_id
 * @property string $status
 *
 * The followings are the available model relations:
 * @property Parser $parser0
 * @property Categories $category
 * @property Goods $parent
 * @property Goods[] $goods
 * @property OrderGoods[] $orderGoods
 */
class Goods extends CBaseActiveRecord
{
	public $property = array();

	public $videos;

	public function setVideos($videos)
	{
		$this->videos = $videos;
	}

	public function getVideos()
	{
		return $this->videos;
	}

	/**
	 * @return string the associated database table name
	 */
	public function tableName()
	{
		return 'sd.goods';
	}

	/**
	 * @return array validation rules for model attributes.
	 */
	public function rules()
	{
		// NOTE: you should only define rules for those attributes that
		// will receive user inputs.
		return array(
			array('title, alias, user_add, date_add', 'required'),
			array('active, is_available, is_new, quantity, user_add, user_edit, sort, is_top, color_bind', 'numerical', 'integerOnly'=>true),
			array('price, old_price, msrp', 'numerical'),
			array('category_id, color_bind, parser_id', 'length', 'max'=>10),
			array('code, status', 'length', 'max'=>45),
			array('title, alias, category_alias, meta_keywords, meta_description, original_url, original_title', 'length', 'max'=>255),
			array('short_description, description, date_edit, original_description, related', 'safe'),
			// The following rule is used by search().
			// @todo Please remove those attributes that should not be searched.
			array('id, code, color_bind, category_id, category_alias, title, alias, short_description, description, meta_keywords, meta_description, active, is_available, is_new, quantity, price, old_price, msrp, user_add, user_edit, date_add, date_edit, sort, original_url, original_title, original_description, is_top, related, parser_id, status', 'safe', 'on'=>'search'),
		);
	}

	/**
	 * @return array relational rules.
	 */
	public function relations()
	{
		// NOTE: you may need to adjust the relation name and the related
		// class name for the relations automatically generated below.
		return array(
			'parser' => array(self::BELONGS_TO, 'Parser', 'parser_id'),
			'category' => array(self::BELONGS_TO, 'Categories', 'category_id'),
			'parent' => array(self::BELONGS_TO, 'Goods', 'parent_id'),
			'orderGoods' => array(self::HAS_MANY, 'OrderGoods', 'goods_id'),
		);
	}

	/**
	 * @return array customized attribute labels (name=>label)
	 */
	public function attributeLabels()
	{
		return array(
			'id' => 'ID',
			'code' => 'Code',
			'color_bind' => 'Color bind id',
			'category_id' => 'Category',
			'category_alias' => 'category_alias',
			'title' => 'Title',
			'alias' => 'Alias',
			'short_description' => 'Short Description',
			'description' => 'Description',
			'meta_keywords' => 'Meta Keywords',
			'meta_description' => 'Meta Description',
			'active' => 'Active',
			'is_available' => 'Is Available',
			'is_new' => 'Is New',
			'quantity' => 'Quantity',
			'price' => 'Price',
			'old_price' => 'Old Price',
			'msrp' => 'msrp',
			'user_add' => 'User Add',
			'user_edit' => 'User Edit',
			'date_add' => 'Date Add',
			'date_edit' => 'Date Edit',
			'sort' => 'Sort',
			'original_url' => 'Original Url',
			'original_title' => 'Original Title',
			'original_description' => 'Original Description',
			'is_top' => 'Is Top',
			'related' => 'Related',
			'parser_id' => 'Parser',
			'status' => 'Status',
		);
	}

	/**
	 * Retrieves a list of models based on the current search/filter conditions.
	 *
	 * Typical usecase:
	 * - Initialize the model fields with values from filter form.
	 * - Execute this method to get CActiveDataProvider instance which will filter
	 * models according to data in model fields.
	 * - Pass data provider to CGridView, CListView or any similar widget.
	 *
	 * @return CActiveDataProvider the data provider that can return the models
	 * based on the search/filter conditions.
	 */
	public function search()
	{
		// @todo Please modify the following code to remove attributes that should not be searched.

		$criteria=new CDbCriteria;

		$criteria->compare('id',$this->id,true);
		$criteria->compare('code',$this->code,true);
		$criteria->compare('color_bind',$this->color_bind,true);
		$criteria->compare('category_id',$this->category_id,true);
		$criteria->compare('category_alias',$this->category_alias,true);
		$criteria->compare('title',$this->title,true);
		$criteria->compare('alias',$this->alias,true);
		$criteria->compare('short_description',$this->short_description,true);
		$criteria->compare('description',$this->description,true);
		$criteria->compare('meta_keywords',$this->meta_keywords,true);
		$criteria->compare('meta_description',$this->meta_description,true);
		$criteria->compare('active',$this->active);
		$criteria->compare('is_available',$this->is_available);
		$criteria->compare('is_new',$this->is_new);
		$criteria->compare('quantity',$this->quantity);
		$criteria->compare('price',$this->price);
		$criteria->compare('old_price',$this->old_price);
		$criteria->compare('msrp',$this->msrp);
		$criteria->compare('user_add',$this->user_add);
		$criteria->compare('user_edit',$this->user_edit);
		$criteria->compare('date_add',$this->date_add,true);
		$criteria->compare('date_edit',$this->date_edit,true);
		$criteria->compare('sort',$this->sort);
		$criteria->compare('original_url',$this->original_url,true);
		$criteria->compare('original_title',$this->original_title,true);
		$criteria->compare('original_description',$this->original_description,true);
		$criteria->compare('is_top',$this->is_top);
		$criteria->compare('related',$this->related,true);
		$criteria->compare('parser_id',$this->parser_id,true);
		$criteria->compare('status',$this->status,true);

		return new CActiveDataProvider($this, array(
			'criteria'=>$criteria,
		));
	}

	/**
	 * Returns the static model of the specified AR class.
	 * Please note that you should have this exact method in all your CActiveRecord descendants!
	 * @param string $className active record class name.
	 * @return Goods the static model class
	 */
	public static function model($className=__CLASS__)
	{
		return parent::model($className);
	}

	public function createUrlId()
	{
		return $this->alias;
	}

	public function status($status)
	{
		$this->getDbCriteria()->addInCondition('status', (array)$status);

		return $this;
	}


	protected $_indexes = 'goods';
	public function getFilterCounts($values, $categoryId = null, &$aProperties = array())
	{
        // Convert pvals to valsp
        $arrPidValues = array();
        foreach($aProperties as $aProperty)
        {
            if(!empty($aProperty['values']))
            {
                foreach($aProperty['values'] as $key => $aValue)
                {
                    $arrPidValues[$aValue['property_id']][$aValue['id']] = $aProperty['values'][$key]->id;//$aProperty['values'][$key];
                }
            }
        }

		$search = new SphinxClient();

		// property counts
		$search->ResetGroupBy();
		$search->ResetFilters();
		$search->SetArrayResult(true);
		$search->SetRankingMode(SPH_RANK_PROXIMITY_BM25);
		$search->SetMatchMode(SPH_MATCH_EXTENDED);
		$search->SetLimits(0, 10000000);

		$search->SetGroupBy('value_id', SPH_GROUPBY_ATTR, 'value_id ASC');
		$search->SetFilterRange('status', 1, 2);

		$properties = array();
		if(!empty($values))
		{
			foreach($values as $valId => $propId)
			{
				$properties[$propId][$valId] = $valId;
			}

			foreach($properties as $vals)
			{
				$search->SetFilter('value_id', $vals);
			}
		}

		if($categoryId > 0)
			$search->SetFilter('category_id', array($categoryId));

		$search->AddQuery('', $this->_indexes);

		// selected values
		if(!empty($properties))
		{
			foreach($properties as $propId => $aVals)
			{
				$search->ResetFilters();
				foreach($properties as $pid => $vals)
				{
					if($pid == $propId)
						$search->SetFilter('value_id', $arrPidValues[$pid]);
					else
						$search->SetFilter('value_id', $vals);
				}

				if($categoryId > 0)
					$search->SetFilter('category_id', array($categoryId));

				$search->AddQuery('', $this->_indexes);
			}
		}

		$res = $search->RunQueries();

//		print_r($res); exit;

		$counts = array();
		$aCounts = array();
		if($res && count($res))
		{
			foreach($res as $key => $sres)
			{
				$prefix = $key == 0 ? '' : '+';
				$type = 'property';
				if(!empty($sres['matches']))
				{
					foreach($sres['matches'] as $data)
					{
						if($key == 0)
							$counts[$type][(int)$data['attrs']['@groupby']] = $data['attrs']['@count'] > 0 ? $data['attrs']['@count'] : 0;
						else
							$aCounts[$key][(int)$data['attrs']['@groupby']] = (int)$data['attrs']['@count'];
					}
				}
			}
		}

//		print_r($aCounts); //exit;
//		print_r($aValues); //exit;

		$i = 1;
		foreach($properties as $pid => $vals)
		{
			foreach($arrPidValues[$pid] as $vid)
			{
				if(isset($aCounts[$i][$vid]))
					$counts['property'][$vid] = '+'.$aCounts[$i][$vid];
			}
			$i++;
		}

		return $counts;
	}

	private function _getSphinxResult($res, $field = null)
	{
		$result = array();
		if(!empty($res['matches']))
		{
			foreach($res['matches'] as $key => $data)
			{
				if(isset($data['attrs']))
				{
					if(!$field)
						$result[$key] = $data['attrs'];
					else if(isset($data['attrs'][$field]))
						$result[$key] = $data['attrs'][$field];
				}
			}
		}

		return $result;
	}

	public function getList($categoryId = null, CPagination $oPager = null, array $filter = array())
	{
		$search = new SphinxClient();

		// property counts
		$search->ResetGroupBy();
		$search->ResetFilters();
//		$search->SetArrayResult (false);
		$search->SetRankingMode(SPH_RANK_PROXIMITY_BM25);
		$search->SetMatchMode(SPH_MATCH_EXTENDED2);
//		$search->SetGroupBy('value_id', SPH_GROUPBY_ATTR);
//		$search->SetFilterRange('status', 1, 2);

        if($oPager)
        {
	        $search->SetLimits(($oPager->getCurrentPage() * $oPager->getPageSize()), $oPager->getPageSize());
        }

		$values = !empty($filter) ? $this->_prepareFilter($filter) : array();

		$properties = array();
		if(!empty($values))
		{
			foreach($values as $valId => $propId)
			{
				$properties[$propId][$valId] = $valId;
//				$search->SetFilter('value_id', array($valId));
			}

			foreach($properties as $propId => $vals)
			{
				$search->SetFilter('value_id', $vals);
			}
		}

		if($categoryId > 0)
			$search->SetFilter('category_id', $categoryId);

        if(!empty($filter['s']))
        {
            switch($filter['s'])
            {
                case 'newest':
                    $search->SetSortMode(SPH_SORT_ATTR_DESC, 'sort_time');
                    break;
                case 'popularity':
                    $search->SetSortMode(SPH_SORT_ATTR_DESC, 'views');
                    break;
                case 'name':
                    $search->SetSortMode(SPH_SORT_ATTR_ASC, 'title_ordinal');
                    break;
                case 'low':
                    $search->SetSortMode(SPH_SORT_ATTR_ASC, 'price');
                    break;
                case 'high':
                    $search->SetSortMode(SPH_SORT_ATTR_DESC, 'price');
                    break;
                case 'off':
                    $search->SetSortMode(SPH_SORT_ATTR_DESC, 'off');
                    break;
            }
        }

		$res = $search->Query('', 'goods');

//		print_r($res); exit;
//		print_r($res['total_found']); exit;

        if($oPager)
        {
            $oPager->setItemCount(0);
            if(isset($res['total_found']))
                $oPager->setItemCount($res['total_found']);
        }

		if(empty($res))
			return array();

		if(empty($res['matches']))
			return array();

		$ids = array_keys($res['matches']);

//        print_r($ids); exit;

		if(!$ids)
			return array();

		$oCriteria = $this->getDbCriteria();
        $oCriteria->addInCondition('t.id', $ids);

        if(!empty($filter['s']))
        {
            switch($filter['s'])
            {
                case 'newest':
                    $oCriteria->order = 'date_add DESC';
                    break;
                case 'popularity':
                    $oCriteria->join = "LEFT JOIN goods_view gv ON gv.goods_id = t.id";
                    $oCriteria->group = "t.id";
                    $oCriteria->order = 'count(t.id) DESC';
                    break;
                case 'name':
                    $oCriteria->order = 't.title ASC';
                    break;
                case 'low':
                    $oCriteria->order = 'price ASC';
                    break;
                case 'high':
                    $oCriteria->order = 'price DESC';
                    break;
                case 'off':
                    $oCriteria->order = '(1-price/old_price) DESC';
                    break;
            }
        }

		return $this->findAll($oCriteria);
	}

	protected function _prepareFilter($filters)
	{
		$aFiltered = array();
		$values = array();
		if(!empty($filters['v']))
		{
//			$filters['v'] = base64_decode($filters['v']);
			$pairs = explode('|', $filters['v']);

			if(count($pairs) > 0)
			{
				foreach($pairs as $pair)
				{
					$values = explode(':', $pair);
					if(!empty($values[0]) && $values[0] > 0 && !empty($values[1]) && $values[1] > 0)
					{
						$aFiltered[$values[1]] = $values[0];
					}
				}
			}
		}
//print_r($aFiltered);
		return $aFiltered;
	}

	public function getListByParentId(array $ids, $oPager = null, $selectCount = true)
	{
		if(!$ids)
			return array();

		$oCriteria = $this->getDbCriteria();

		$oCriteria->addInCondition('id', (array)$ids);

		if($oPager)
		{
			if($selectCount)
				$oPager->setItemCount($this->count($oCriteria));
			$oPager->applyLimit($oCriteria);
		}

		return $this->findAll($oCriteria);
	}

	public function getAll($oPager = null, $categoryId = null)
	{
		$oCriteria = $this->getDbCriteria();

		$oCriteria->order = 'id DESC';

		if($categoryId > 0)
			$oCriteria->addColumnCondition(array('category_id' => $categoryId));

		if($oPager)
		{
			$oPager->setItemCount($this->count($oCriteria));
			$oPager->applyLimit($oCriteria);
		}

		return $this->findAll($oCriteria);
	}

	public function getTop($limit)
	{
		$oCriteria = $this->getDbCriteria();
		$oCriteria->condition = 'is_top = 1 AND price > 0';
		$oCriteria->order = 'RAND()';

		if($limit > 0)
			$oCriteria->limit = $limit;

		return array();//$this->findAll($oCriteria);
	}

	public function getAllColors($oRow)
	{
		if(!$oRow)
			return array();

		if(!$oRow->color_bind)
			$oRowset = $this->findAllByPk($oRow->id);
		else
			$oRowset = $this->findAllByAttributes(array(
			                                           'color_bind' => $oRow->color_bind,
			                                      ));

		return $oRowset;
	}


	public function saveRow($row)
	{
		$row['is_top'] = !empty($row['is_top']) ? 1 : 0;

//		print_r($rowset); exit;

		$aRow = $row;
		$oRow = array();
		if(!empty($aRow['category_id']) && $aRow['category_id'] > 0)
		{
			$oCategory = new \Categories();
			$oCategory = $oCategory->findByAttributes(array('id' => $aRow['category_id']));
			$aRow['category_alias'] = $oCategory->alias;
		}

		$id = 0;
		if(!empty($aRow['id']) && $aRow['id'] > 0)
		{
			$id = $aRow['id'];
			unset($aRow['id']);
		}

		if($id > 0)
			$oRow = $this->findByPk($id);

		if($oRow && $oRow->id > 0)
		{
			$aRow['date_edit'] = date('Y-m-d H:i:s');
			$aRow['user_edit'] = $aRow['user_id'];
		}

		if(!$oRow)
		{
			$oRow = new self;

			$aRow['date_add']  = date('Y-m-d H:i:s');
			$aRow['user_add']  = $aRow['user_id'];
		}

		if(!empty($aRow['title']))
		{
			$aRow['alias'] = $this->generateAlias($oRow->id, $aRow['title']);
		}

		if(empty($aRow['relative_id']))
			$aRow['relative_id'] = 0;

		if(!empty($aRow['description']))
			$aRow['description'] = String::stripTagsAttributes(
				$aRow['description'],
				'<p><h2><dt><dd><dl><img><ul><li><ol><a><iframe><object><param><embed>',
				array('href', 'src', 'alt', 'title', 'width', 'height')
			);

		$oRow->setAttributes($aRow);
		$oRow->save(true);


		if($oRow && $oRow->getPrimaryKey() > 0 && !empty($row['to_social']) && $row['to_social'] > 0)
		{
			$oSocial = new Social();
			$oSocial->setHandler(new SocialFacebook())
					->init()
					->post(
						$oRow->title,
						String::substr(String::stripTagsAttributes($oRow->description), '300'),
						Yii::app()->controller->createAbsoluteUrl('default/view', array(
							'id' => $oRow->alias,
							'category' => $oRow->category_alias
						))
					);
		}

		return $oRow;
	}


	public function saveParsedRow($aRow, $aUrl, $aCategories = array())
	{
		$oGoods = new Goods();
		$oGoodsRow = $oGoods->findByAttributes(array(
			'original_url' => $aRow['url']
		));

		$oPropertyValue = new PropertyValue();
		$oPropertyValue = $oPropertyValue->findByValue($aRow['vendor'], 5);

		$isNewRow = false;
		if(!$oGoodsRow)
		{
			$oGoodsRow = new Goods();

			$title = $aRow['vendor'].' '.$aRow['title'];
			$alias = $oGoodsRow->generateAlias(($oGoodsRow && $oGoodsRow->id ? $oGoodsRow->id : null), $title);

			$oGoodsRow->setAttributes(array(
				'category_id' => $aUrl[$aRow['url']]['category_id'],
				'parser_id' => $aUrl[$aRow['url']]['parser_id'],
				'title' => $title,
				'original_title' => $title,
				'alias' => $alias,
				'category_alias' => !empty($aCategories[$aUrl[$aRow['url']]['category_id']]) ? $aCategories[$aUrl[$aRow['url']]['category_id']]->alias : '',
				'short_description' => String::substr(String::stripTagsAttributes($aRow['description']), 200),
				'description' => String::stripTagsAttributes($aRow['description'], '<img><p><span><ul><ol><li><div><dl><dt><dd>'),
				'original_description' => $aRow['description'],
				'price' => $aRow['price'],
				'user_add' => 1,
				'date_add' => date('Y-m-d H:i:s'),
				'original_url' => $aRow['url'],
				'active' => 1,
				'is_available' => 1,
				'is_new' => 0,
				'quantity' => 1,
				'sort' => 0,
				'status' => 1,
			));

			$isNewRow = true;
//                print_r($oGoodsRow); exit;
		}

		$oGoodsRow->price = $aRow['price'];

		if($oGoodsRow->save(true) && $isNewRow)
		{
			$oGoodsRow->color_bind = $oGoodsRow->getPrimaryKey();
			$oGoodsRow->save();
		}

		if(!empty($oPropertyValue) && !empty($oGoodsRow) && $oGoodsRow->getPrimaryKey() > 0)
		{
			$oGoodsProperty = new GoodsProperty();

			$oGoodsProperty->setAttributes(array(
				'goods_id' => $oGoodsRow->getPrimaryKey(),
				'property_id' => $oPropertyValue->property_id,
				'value_id' => $oPropertyValue->id
			));

			$oGoodsProperty->save();
		}

		if(!empty($aRow['photos']) && $oGoodsRow)
		{
			$i = 0;
			foreach($aRow['photos'] as $imgSrc)
			{
				$oPhoto = new Photos();
				$oPhoto = $oPhoto->findByAttributes(array('original_url' => $imgSrc));

				if($oPhoto && $oPhoto->id > 0)
					continue;

				$oThumb = new Thumbnail($imgSrc);
				$result = $oThumb->crop('/-/', Yii::app()->params->photos[$oGoodsRow->getTableName()], $oGoodsRow->alias, $oGoodsRow->getPrimaryKey());

				if($result)
				{
					$oPhoto = new Photos();
					$oPhoto->attributes = array(
						'target_type' => $oGoodsRow->getTableName(),
						'target_id' => $oGoodsRow->getPrimaryKey(),
						'path' => $result['dir'],
						'file' => $result['file'],
						'upload_user' => 1,
						'upload_time' => time(),
						'is_main' => ($i++ == 0 ? 1 : 0),
						'original_url' => $imgSrc
					);
					$oPhoto->save();
				}
				else
				{
					$oGoodsRow->delete();
				}
			}
		}

		if(!empty($aRow['video']) && $oGoodsRow)
		{
			$oVideo = new Video();
			$oVideo->setAttributes(array(
                'target_id' => $oGoodsRow->getPrimaryKey(),
                'target_type' => $oGoodsRow->getTableName(),
                'path' => '', 'file' => '', 'title' => '',
				'url' => '',
				'code' => '<iframe src="'. $aRow['video'] .'"></iframe>',
			    'upload_time' => time()
			));

			$oVideo->save(true);
		}

		return $oGoodsRow->getPrimaryKey();
	}

	public function getSitemapList(CPagination $oPager)
	{
		$oCriteria = $this->getDbCriteria();
		$oCriteria->select = 'alias, category_alias, date_add';
//		$oCriteria->addInCondition('status', array(1, 2));
		$oCriteria->addCondition(array(), 'price > 0');

		$oPager->setItemCount($this->count($oCriteria));
		$oPager->applyLimit($oCriteria);

		return $this->findAll($oCriteria);
	}

}
